//此插件依赖xlsl.js
//@author zhoulianli 2022-04-15
//此插件主要用来导出表格数据，在xlsl.js基础上封装了列宽自适应，表头标题替换功能

//使用方法 jsonToxlsx(参数)
//参数1: 表格数据 [{},{}]
//参数2：可选，表头标题映射数据 {name:"姓名",age:"年龄"}
//参数3：可选，文件名 例如："数据导出"
//参数4：可选，sheet名 例如："能耗比数据"

//闭包  传入当前环境的this
(function (global, factory) {
    //1.先判断当前环境是否支持CommonJS规范(node.js)
    if (typeof exports == 'object' && typeof module !== 'undefined') {
        //console.log('CommonJS规范')
        module.exports = factory()
    } else if (typeof define == 'function' && define.amd) {//2.再判断是否支持AMD规范(require.js)
        //console.log('AMD规范')
        define(factory)
    } else {
        //console.log('script标签引入')
        //接收该对象
        this.jsonToxlsx = factory()
    }
}(this,function(){
    //将表格数组导出的方法
    function jsonToxlsx(tableData = [],tHeadMap = {},fileName = "数据导出",sheetName = "数据导出"){
        //判断依赖是否存在
        if(typeof XLSX == undefined){
            console.log('请先引入XLSX.js')
            return
        }
        
        //替换数组中对象的属性名
        var print_data = replaceKeyForTableData(tableData,tHeadMap)

        // 创建一个新sheet
        const new_sheet = XLSX.utils.json_to_sheet(print_data)

        // 根据每列数据智能设定列宽
        var two_dimensional_arr = transformToTwoDimensional(print_data)
        var width_arr = two_dimensional_arr.map(arr=>{
            return {
                wch: getMaxLenByArr(arr) + 2
            }
        })
        new_sheet['!cols'] = width_arr

        // 新建book
        const new_book = XLSX.utils.book_new()
        // 将 sheet 添加到 book 中
        XLSX.utils.book_append_sheet(new_book, new_sheet, sheetName)
        // 导出excel文件
        XLSX.writeFile(new_book, `${fileName}.xlsx`)
    }

    //替换数组中对象的属性名
    function replaceKeyForTableData(tableData = [],mapData = {}){
        //要返回的最终数据
        var result = []
        //循环数组的每行数据
        tableData.forEach(row=>{
            //新的行数据
            var new_row = {}
            //循环每个键值
            Object.keys(row).forEach(key=>{
                //判断这个可以是否 可以在映色中找到对应的值 有则使用，无则使用原来的key
                var new_key = mapData[key]? mapData[key]:key
                //为新的行数据添加键值对
                new_row[new_key] = row[key]
            })
            //新的行添加到表格数据中
            result.push(new_row)
        })
        return result
    }

    //将表格数组转换为二维数组 [[col1-1,col1-2],[col2-1,col2-2]]
    function transformToTwoDimensional(tableData){
        //如果数据源为空 则返回空
        if (tableData == 0) {
            return []
        }
        //对象有多少个key，就有多少列，每列数据是一个数组

        //先填充标题
        var result = []
        for (key in tableData[0]) {
            result.push([key])
        }

        //接着填充数据
        tableData.forEach(row => {
            var index = 0
            for (key in row) {
                result[index].push(row[key])
                index++
            }
        })

        return result
    }


    //从一维数组中提取出 最大的字节占位
    function getMaxLenByArr(strArr){
        var max = 0
        strArr.forEach(item => {
            //转为字符串
            var str = item + ''
            var strlen = 0;
            for (var i = 0; i < str.length; i++) {
                if (str.charCodeAt(i) > 255) //如果是汉字，则字符串长度加2
                    strlen += 2;
                else
                    strlen++;
            }
            if( strlen > max){
                max = strlen
            }
        })
        return max
    }
    return jsonToxlsx;
}))
